package com.zzyl.nursing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.constant.Constants;
import com.zzyl.nursing.domain.AlertData;
import com.zzyl.nursing.domain.AlertRule;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.mapper.AlertDataMapper;
import com.zzyl.nursing.mapper.AlertRuleMapper;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.service.IAlertRuleService;
import com.zzyl.system.mapper.SysUserRoleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 报警功能Service业务层处理
 * 
 * @author zhq
 * @date 2025-08-26
 */
@Service
public class AlertRuleServiceImpl extends ServiceImpl<AlertRuleMapper, AlertRule> implements IAlertRuleService
{
    @Autowired
    private AlertRuleMapper alertRuleMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AlertDataMapper alertDataMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void alertFilter() {
        //1.统计规则数量,如果没有,直接结束
        Long count = alertRuleMapper.selectCount(new LambdaQueryWrapper<AlertRule>().eq(AlertRule::getStatus, 1));
        if(count <0){
            return;
        }
        //2.从redis中获取所有设备上报的数据
        List<List<DeviceData>> values = redisTemplate.opsForHash().values(Constants.IOT_DEVICE_LAST_DATA);

        //3.没有数据,直接结束
        if(CollUtil.isEmpty(values)){
            return;
        }
        //4.开始遍历数据,处理每一条数据,是否满足报警规则
        List<DeviceData> allDeviceData=new ArrayList<>();
        values.forEach(dataList->{
            dataList.forEach(
                    data->{
                        dataAlertFilter(data);
                    }
            );
        });

    }

    private void dataAlertFilter(DeviceData data) {
        //1.判断时间是否在一分钟内
        if (data.getAlarmTime().plusMinutes(1).isBefore(LocalDateTime.now())) {
            return;
        }
        //2.获取产品下设备的对应的物模型规则
        List<AlertRule> alertRules = alertRuleMapper.selectList(
                new LambdaQueryWrapper<AlertRule>()
                        .eq(AlertRule::getProductKey, data.getProductKey())
                        .in(AlertRule::getIotId, -1, data.getIotId())
                        .eq(AlertRule::getFunctionId, data.getFunctionId())
        );
        //3.判断规则是否为空,为空直接结束
        if (CollUtil.isEmpty(alertRules)){
            return;
        }
        //4.遍历每一条规则
        alertRules.forEach(
                rule->dataIsMatchRule(rule,data)
        );

    }
    //周期
    private void dataIsMatchRule(AlertRule rule, DeviceData data) {
        String durationKey ="duration"+ data.getProductKey ()+ "" + data.getIotId()+ "" + data.getFunctionId();
        String silentKey ="silent"+ data.getProductKey ()+ "" + data.getIotId()+ "" + data.getFunctionId();
        
        //1.判断是否在生效时间内,不在,直接结束
        if(!alarmTimeIsMatch(rule,data)){
            return;
        }
        //2.判断数据是否达到阈值
        Double dataAlert= (Double) data.getDataValue();
        if ((">=".equals(rule.getOperator())&& Double.compare(dataAlert,rule.getValue())<0)||
                ("<".equals(rule.getOperator())&& Double.compare(dataAlert,rule.getValue())>0)){
            redisTemplate.delete(durationKey);
            return;
        }
        //3.判断是否沉默周期
        if(ObjectUtil.isNotEmpty(redisTemplate.opsForValue().get(silentKey))){
            return;
        }
        //4.查询已报警次数,如果为没有设置为1,如果有加1,如果到持续周期,则删除持续周期,如果到沉默周期,则删除沉默周期
        Integer alertCount = (Integer) redisTemplate.opsForValue().get(durationKey);
        if(ObjectUtil.isNull(alertCount)){
            alertCount=1;
            return;
        }else if(alertCount>=rule.getDuration()){
            redisTemplate.delete("durationKey");
        }else {
            alertCount++;
            redisTemplate.opsForValue().set("durationKey",alertCount);
            return;
        }
        //5.设置沉默周期
        redisTemplate.opsForValue().set(silentKey,1,rule.getAlertSilentPeriod(), TimeUnit.MINUTES);
        //6.删除持续周期
        redisTemplate.delete("durationKey");
        //6.告知相关人员,保存数据
        saveBatch(rule, data);

    }

    private void saveBatch(AlertRule rule, DeviceData data) {
        List<Long> admins = sysUserRoleMapper.selectUserIdsByRoleName("超级管理员");
        List<Long> others=null;
        if(rule.getAlertDataType().equals(0)){
            if(data.getLocationType()==0){
                 others= deviceMapper.selectNursingIdsByIotIdWithElder(data.getIotId());
            }else {
                others=deviceMapper.selectNursingIdsByIotIdWithBed(data.getIotId());
            }
        }else {
            others=sysUserRoleMapper.selectUserIdsByRoleName("维修工");
        }
        Collection<Long> staff= CollUtil.addAll(admins, others);
        staff.remove(null);
        staff.forEach(
                userId->{
                    AlertData bean = BeanUtil.toBean(data, AlertData.class);
                    bean.setId(null);
                    bean.setAlertRuleId(rule.getId());
                    bean.setAlertReason(StrUtil.format("报警原因：{},{},{},持续周期{}", rule.getFunctionName(), rule.getOperator(), rule.getValue(), rule.getDuration()));
                    bean.setType(rule.getAlertDataType());
                    bean.setStatus(0);
                    bean.setUserId(userId);
                    alertDataMapper.insertAlertData(bean);
                }
        );
    }

    private boolean alarmTimeIsMatch(AlertRule rule, DeviceData data) {
        String[] split = rule.getAlertEffectivePeriod().split("~");
        LocalTime start = LocalTime.parse(split[0]);
        LocalTime end =LocalTime.parse(split[1]);
        LocalTime alarmTime = data.getAlarmTime().toLocalTime();
        if (alarmTime.isBefore(start) || alarmTime.isAfter(end)){
            return false;
        }
        return true;
    }

    /**
     * 查询报警功能
     * 
     * @param id 报警功能主键
     * @return 报警功能
     */
    @Override
    public AlertRule selectAlertRuleById(Long id)
    {
        return alertRuleMapper.selectById(id);
    }

    /**
     * 查询报警功能列表
     * 
     * @param alertRule 报警功能
     * @return 报警功能
     */
    @Override
    public List<AlertRule> selectAlertRuleList(AlertRule alertRule)
    {
        return alertRuleMapper.selectAlertRuleList(alertRule);
    }

    /**
     * 新增报警功能
     * 
     * @param alertRule 报警功能
     * @return 结果
     */
    @Override
    public int insertAlertRule(AlertRule alertRule)
    {
        return alertRuleMapper.insert(alertRule);
    }

    /**
     * 修改报警功能
     * 
     * @param alertRule 报警功能
     * @return 结果
     */
    @Override
    public int updateAlertRule(AlertRule alertRule)
    {
        return alertRuleMapper.updateById(alertRule);
    }

    /**
     * 批量删除报警功能
     * 
     * @param ids 需要删除的报警功能主键
     * @return 结果
     */
    @Override
    public int deleteAlertRuleByIds(Long[] ids)
    {
        return alertRuleMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除报警功能信息
     * 
     * @param id 报警功能主键
     * @return 结果
     */
    @Override
    public int deleteAlertRuleById(Long id)
    {
        return alertRuleMapper.deleteById(id);
    }
}
